#include "my_cleanup.h"

my_cleanup_list_t g_cleanup_list = {
    .lock = MY_SPINLOCK_INITLIZER,
    .head = {NULL, NULL, NULL}
};

void
my_cleanup_list_init(my_cleanup_list_t *list)
{
    my_spinlock_init(&list->lock);
    list->head.handler = NULL;
    list->head.data = NULL;
    list->head.next = NULL;
}


void
my_cleanup_handler_add(my_cleanup_list_t *list, 
    my_cleanup_handler_pt handler, void *data)
{
    my_cleanup_item_t *item = my_calloc(sizeof(my_cleanup_item_t));
    item->handler = handler;
    item->data = data;

    my_spinlock_lock(&list->lock);
    item->next = list->head.next;
    list->head.next = item;
    my_spinlock_unlock(&list->lock);
}

void
my_cleanup_list_exec(my_cleanup_list_t *list)
{
    my_cleanup_item_t *item = NULL;

    my_spinlock_lock(&list->lock);
    while ((item = list->head.next)) {
        item->handler(item->data);
        list->head.next = item->next;
        my_free(item);
    }
    my_spinlock_unlock(&list->lock);
}